#include	<stdio.h>
#include 	<string.h>

typedef struct info_uc {
   char uc[5];        /* Abreviatura da unidade curricular: POO, ALGA, ... */
   char tipo;         /* Tipo: B-obrigatória, P-opcional, C-complementar */
   unsigned char sem; /* Bitmap dos semestres em que funciona */
   struct info_uc *depF[3]; /* Dependências fortes: NULL se não existe */
   struct info_uc *depf[3]; /* Dependências fracas: NULL se não existe */
} InfoUC;

InfoUC curso [50];
int size = 0;

void addName(char *uc){
	strcpy(curso[size].uc, uc);
}

void addType(char *type){
	curso[size].tipo = *type;
}

void addSem(char * sem){
	if(*(sem + 1) == 0)
		curso[size].sem = *sem - '0';
	else
		curso[size].sem = (*sem - '0')*10 + *(sem+1)-'0';
}

void Search(char* pes, char selec){

	InfoUC * pCurso = curso;
	int i=0;
		
		switch (selec){
			
			case '0':{
				//definição da MASK para pesquisa por semestre
				int sem = 1<<(((*pes)-'0')-1);
				
				while(i < size){

					if(pCurso->sem & sem )
						puts(pCurso->uc);

					++i;
					++pCurso;
				}
				break;
			}
			
			case '1':{
				
				while(i < size){
					
					if(pCurso->tipo == *pes)
						puts(pCurso->uc);

					++i;
					++pCurso;
				}
				break;
			}
			
			case '2':{
				
				while(i < size){
				
					int idx = 0;
					
					while(idx < 3 && (pCurso->depF[idx] != NULL)){
					
						if(strcmp(pCurso->depF[idx]->uc, pes) == 0)
							puts(pCurso->uc);
	
						++idx;
					}
					++i;
					++pCurso;
				}
				break;
			}	
		
	}

}

InfoUC * SearchIntoArray (char* disp){

	InfoUC * pCurso = curso;
	int i=0;
	
	while(i< size){
		
		if(strcmp(pCurso->uc, disp) == 0)
			return pCurso;
			
		++i;
		++pCurso;
	}
	return 0;
}

void addDepForte(char *dep){
	
	int idxF = 0;
	char uc[5]; 
	char * pUc = uc;


	if(*dep == 0){
		
		for(;idxF < 3; ++idxF)
			curso[size].depF[idxF] = NULL;
			
		return;
	}

	for(;;){
			
		if((*dep != ';' )&& (*dep != 0)){
			*pUc = *dep;
			++pUc;
		}
		else{
			
			*pUc=0;
			
			InfoUC * aux = SearchIntoArray(uc);
			
			if(aux)
				curso[size].depF[idxF++] = aux;
				
			else{
				
				InfoUC new;
				strcpy(new.uc, dep);
				curso[size].depF[idxF++] = &new;
			
			}
			pUc = uc;
		}	
		
		if(*dep == 0)
			break;
		
		++dep;
		
	}
		
}

void addDepFraca(char *dep){
	
	int idxf = 0;
	char uc[5]; 
	char * pUc = uc;

	if(*dep == 0){
		
		for(;idxf < 3; ++idxf)
			curso[size].depf[idxf] = NULL;
			
		return;
	}
	
	for(;;){
			
		if((*dep != ';' )&& (*dep != 0)){
			*pUc = *dep;
			++pUc;
		}
		else{
			
			*pUc=0;
			
			InfoUC * aux = SearchIntoArray(uc);
			
			if(aux)
				curso[size].depf[idxf++] = aux;
				
			else{
				
				InfoUC new;
				strcpy(new.uc, dep);
				curso[size].depf[idxf++] = &new;
			
			}
			pUc = uc;
		}	
		
		if(*dep == 0)
			break;
		
		++dep;
		
	}
		
}

void readFile (){	
	
	char str [13]; //String STR 
	char *pointStr = str;
	int barCount = 0;
		
	int c;
	while((c = getchar())!= EOF){
		
		if(c == '\n'){
			pointStr = str;
			++size;
		}
		
		if(c != '|' && c != '\n'){
			
			*pointStr = c;
			++pointStr;

		}
		else{
			//colocar o terminador de "String"
			*pointStr = 0;
			
			switch (barCount){
						
				case 0:{
					addName(str);
					pointStr = str;
					break;
				}
						
				case 1:{
					addType(str);
					pointStr = str;
					break;
				}
							
				case 2:{
					addSem(str);
					pointStr = str;
					break;
				}		
						
				case 3:{
					addDepForte(str);
					pointStr = str;
					break;
				}		
						
				case 4:{
					addDepFraca(str);
					pointStr = str;
					
					barCount = -1; //depois de ter adicionado todos limpa o barCount compensador com ++barCount
					
					break;
				}
						
			}
			++barCount;	
		}

	}
	
}

//SERIE 2

void * ssearch(const void * key, const void * base, size_t size,
        size_t elem_size, int (* compare)(const void * k, const void * p));

/* 
@param 
	*s1 - recebe o ponteiro para a Unidade curricular
	*s2 - recebe o ponteiro para o semestre que pretende procurar

@return
	retorna zero se for diferente, e diferente de zero se for igual
*/

int cmpSemestre(const void * k, const void * p){
	
	//char * s2 = (char*) k;
	char s2 = *(char*) k;
	InfoUC * uc = (InfoUC*) p;
	
	//definição da MASK para pesquisa por semestre
	int sem = 1<<((s2-'0')-1);
	
	if(uc->sem & sem)
		return 0;
	
	return ~(uc->sem & sem);	
}
/*
 @param 
	uc - recebe o ponteiro para a Unidade curricular
	type - recebe o ponteiro para o tipo a pesquisar
*/
int cmpTipo(const void * k, const void * p){
	
	char * type = (char*) k;
	InfoUC * uc = (InfoUC*) p;
	
	if(uc->tipo == *type)
		return 0;
		
	return ~(uc->tipo == *type);
	
}
//incompleto
/*int cmpDepF(const InfoUC * uc, const ){
	
	while(idx < 3 && (pCurso->depF[idx] != NULL)){
					
		InfoUC* aux = pCurso->depF[idx];
		puts(pCurso->uc);
				
	}
}*/


int main(int argc,char * argv[]){
	char arg1 = '1';
	char* pes = "B";

	char* type = &arg1;
	
	readFile();
	
	InfoUC* fi = (InfoUC*)ssearch(pes,curso,30, sizeof(InfoUC),  cmpTipo);
	
	puts(fi->uc);
	
	Search(pes, *type);

	return 0;
}
